﻿@page "/sync"
@layout EmptyLayout
@implements IDisposable
@using AliasVault.Client.Auth.Pages.Base
@using AliasVault.Client.Main.Pages.Sync.StatusMessages
@inject DbService DbService
@inject AuthService AuthService
@inject ILocalStorageService LocalStorage
@inject NavigationManager NavigationManager
@inject ILogger<Sync> Logger
@inject IStringLocalizerFactory LocalizerFactory
@inject LanguageService LanguageService
@using Microsoft.Extensions.Localization

<LayoutPageTitle>@Localizer["PageTitle"]</LayoutPageTitle>

<div class="fixed inset-0 flex flex-col items-center justify-center px-6 pt-8 pb-8 h-full w-full">
    @if (CurrentDbState.Status == DbServiceState.DatabaseStatus.DecryptionFailed)
    {
        <ErrorVaultDecrypt />
    }
    else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.VaultVersionUnrecognized)
    {
        <ErrorVaultNotSupported />
    }
    else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.PendingMigrations)
    {
        <PendingMigrations />
    }
    else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.MergeFailed)
    {
        <ErrorVaultMerge message="@CurrentDbState.Message" />
    }
    else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.MergeRequired)
    {
        <Merging />
    }
    else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.Creating)
    {
        <Creating />
    }
    else
    {
        <VaultDecryptionProgress />
    }

    <div class="text-sm font-medium text-gray-500 dark:text-gray-400 mt-6">
        @Localizer["SwitchAccountsText"] <a href="/user/logout" class="text-primary-700 hover:underline dark:text-primary-500">@Localizer["LogoutLink"]</a>
    </div>
</div>


@code {
    private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Main.Sync.Sync", "AliasVault.Client");
    private DbServiceState.DatabaseState CurrentDbState { get; set; } = new();
    private const int MinimumLoadingTimeMs = 800;

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        CurrentDbState = DbService.GetState().CurrentState;

        // Check that encryption key is set. If not, redirect to unlock screen.
        if (!AuthService.IsEncryptionKeySet())
        {
            NavigationManager.NavigateTo("/unlock");
        }

        await CheckAndInitializeDatabase();
        DbService.GetState().StateChanged += OnDatabaseStateChanged;
    }

    private async Task CheckAndInitializeDatabase()
    {
        CurrentDbState = DbService.GetState().CurrentState;
        if (CurrentDbState.Status == DbServiceState.DatabaseStatus.Uninitialized)
        {
            await InitializeDatabaseWithProgress();
        }
        else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.Ready)
        {
            await NavigateToHome();
        }

        StateHasChanged();
    }

    private async void OnDatabaseStateChanged(object? sender, DbServiceState.DatabaseState newState)
    {
        CurrentDbState = DbService.GetState().CurrentState;
        if (CurrentDbState.Status == DbServiceState.DatabaseStatus.Uninitialized)
        {
            await InitializeDatabaseWithProgress();
        }
        else if (CurrentDbState.Status == DbServiceState.DatabaseStatus.Ready)
        {
            await NavigateToHome();
        }

        Logger.LogDebug("Database state changed: {NewStatus}", CurrentDbState.Status);
        StateHasChanged();
    }

    private async Task InitializeDatabaseWithProgress()
    {
        StateHasChanged();

        var stopwatch = System.Diagnostics.Stopwatch.StartNew();

        await DbService.InitializeDatabaseAsync();

        stopwatch.Stop();
        var elapsedMs = (int)stopwatch.ElapsedMilliseconds;

        if (elapsedMs < MinimumLoadingTimeMs)
        {
            await Task.Delay(MinimumLoadingTimeMs - elapsedMs);
        }

        await CheckAndInitializeDatabase();
        StateHasChanged();
    }

    private async Task NavigateToHome()
    {
        // Apply vault language settings after database is ready
        try
        {
            var currentLanguage = await LanguageService.GetCurrentLanguageAsync();
            await LanguageService.SetLanguageAsync(currentLanguage);
        }
        catch (Exception ex)
        {
            Logger.LogWarning(ex, "Failed to apply vault language settings");
            // Continue with navigation even if language setting fails
        }

        var disallowedUrls = new[] { "/sync", "/unlock", "/user/logout" };
        var localStorageReturnUrl = await LocalStorage.GetItemAsync<string>(LoginBase.ReturnUrlKey);

        if (string.IsNullOrEmpty(localStorageReturnUrl))
        {
            // Navigate to the default entry page.
            NavigationManager.NavigateTo("/");
            return;
        }

        var trimmedUrl = localStorageReturnUrl.Trim();
        if (!string.IsNullOrEmpty(trimmedUrl) && !disallowedUrls.Contains(localStorageReturnUrl))
        {
            // If an explicit return URL has been configured, redirect to that URL.
            await LocalStorage.RemoveItemAsync(LoginBase.ReturnUrlKey);
            NavigationManager.NavigateTo(localStorageReturnUrl);
        }
        else
        {
            // Navigate to the default entry page.
            NavigationManager.NavigateTo("/");
        }
    }

    /// <inheritdoc />
    public void Dispose()
    {
        DbService.GetState().StateChanged -= OnDatabaseStateChanged;
    }
}
